package com.TripMate.system.controller;

import com.TripMate.system.annotation.AuthCheck;
import com.TripMate.system.common.BaseResponse;
import com.TripMate.system.common.DeleteRequest;
import com.TripMate.system.common.ErrorCode;
import com.TripMate.system.common.ResultUtils;
import com.TripMate.system.constant.UserConstant;
import com.TripMate.system.exception.BusinessException;
import com.TripMate.system.exception.ThrowUtils;
import com.TripMate.system.model.dto.chat.AiHistoryByMyQueryRequest;
import com.TripMate.system.model.dto.chat.AiHistoryQueryRequest;
import com.TripMate.system.model.dto.chat.ChatRequest;
import com.TripMate.system.model.entity.AiHistory;
import com.TripMate.system.model.entity.User;
import com.TripMate.system.model.vo.AiHistoryByMyVO;
import com.TripMate.system.model.vo.AiHistoryVO;
import com.TripMate.system.model.vo.LoginUserVO;
import com.TripMate.system.service.AiHistoryService;
import com.TripMate.system.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 旅行助手接口
 *
 * @author dongyanmian
 */
@RestController
@RequestMapping("/chat")
@Slf4j
@Api(tags = "ai 旅行助手接口")
public class ChatController {
    @Resource
    private AiHistoryService aiHistoryService;

    @Resource
    private UserService userService;

    /**
     * 获取当前登录用户
     *
     * @param request
     * @return
     */
    @GetMapping("/get/login")
    public BaseResponse<LoginUserVO> getLoginUser(HttpServletRequest request) {
        User user = userService.getLoginUser(request);
        return ResultUtils.success(userService.getLoginUserVO(user));
    }

    @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation("新增 ai 聊天")
    public Flux<String> addChat(@RequestBody ChatRequest chatRequest, HttpServletRequest request) {
        log.info("收到请求: {}", chatRequest);
        Date start = new Date();
        if (chatRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }
        Long id = getLoginUser(request).getData().getId();
        if (id == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在，请重新登录");
        }
        Flux<String> result = aiHistoryService.handleChat(chatRequest);
        log.info("请求参数: {}", chatRequest);
        AiHistory aiHistory = new AiHistory();
        aiHistory.setUserId(id);
        aiHistory.setUserQuestion(chatRequest.getContent());

        // 使用单线程处理，确保不会重复处理
        return result.publishOn(Schedulers.single()).doOnNext(response -> {
            log.info("AI 回答: {}", response);
            aiHistory.setAiAnswer(response);
            boolean save = aiHistoryService.save(aiHistory);
            if (!save) {
                log.error("保存 ai 聊天记录失败");
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "保存 ai 聊天记录失败");
            }
            Date end = new Date();
            log.info("请求耗时: {}", end.getTime() - start.getTime());
        }).doOnError(e -> log.error("处理请求时发生错误: {} " + "请重新尝试", e.getMessage(), e)).onErrorResume(e -> Mono.just("处理请求时发生错误: " + e.getMessage()));

    }

    /**
     * 删除 ai 历史记录
     *
     * @param deleteRequest
     * @param request
     * @return
     */
    @PostMapping("/delete")
    @ApiOperation("删除 ai 历史记录（管理员可以删除任意的历史记录）")
    public BaseResponse<Boolean> deleteChat(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "用户未登录");
        }
        QueryWrapper<User> queryUser = new QueryWrapper<>();
        queryUser.eq("id", loginUser.getId());
        User user = userService.getOne(queryUser);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }
        AiHistory aiHistory = new AiHistory();
        QueryWrapper<AiHistory> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", deleteRequest.getId());
        aiHistory = aiHistoryService.getOne(queryWrapper);
        if (aiHistory == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "历史记录不存在");
        }
        if (!user.getId().equals(aiHistory.getUserId()) && !userService.isAdmin(loginUser)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限删除历史记录");
        }
        boolean result = aiHistoryService.removeById(deleteRequest.getId());
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "删除失败");
        return ResultUtils.success(result);
    }

    /**
     * 查询全部 ai 历史记录
     *
     * @param request
     * @return
     * @RequestBody aidHistoryQueryRequest
     */
    @PostMapping("/get/all")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    @ApiOperation(value = "查询全部 ai 历史记录（仅管理员）")
    public BaseResponse<Page<AiHistoryVO>> getAllChat(@RequestBody AiHistoryQueryRequest aidHistoryQueryRequest, HttpServletRequest request) {

        long current = aidHistoryQueryRequest.getCurrent() == 0 ? 1 : aidHistoryQueryRequest.getCurrent();
        long size = aidHistoryQueryRequest.getPageSize() == 0 ? 10 : aidHistoryQueryRequest.getPageSize();

        Page<AiHistoryVO> pageParam = new Page<>(current, size);
        Page<AiHistoryVO> aiHistoryVOPage = aiHistoryService.getQueryByAll(pageParam, aidHistoryQueryRequest);
        if (aiHistoryVOPage == null) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "查询失败");
        }
        return ResultUtils.success(aiHistoryVOPage);
    }

    /**
     * 查询用户的 ai 历史记录
     *
     * @param request
     * @return
     * @RequestBody aidHistoryQueryRequest
     */
    @PostMapping("/get/all/my")
    @ApiOperation(value = "查询用户的 ai 历史记录")
    public BaseResponse<Page<AiHistoryByMyVO>> getAllMyChat(@RequestBody AiHistoryByMyQueryRequest aidHistoryByMyQueryRequest, HttpServletRequest request) {

        long current = aidHistoryByMyQueryRequest.getCurrent() == 0 ? 1 : aidHistoryByMyQueryRequest.getCurrent();
        long size = aidHistoryByMyQueryRequest.getPageSize() == 0 ? 10 : aidHistoryByMyQueryRequest.getPageSize();

        Long userId = userService.getLoginUser(request).getId();
        if (userId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在，请重新登录");
        }

        Page<AiHistoryVO> pageParam = new Page<>(current, size);
        Page<AiHistoryVO> aiHistoryVOPage = aiHistoryService.getQueryByMy(pageParam, aidHistoryByMyQueryRequest, userId);
        if (aiHistoryVOPage == null) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "查询失败");
        }

        // 转换方法
        List<AiHistoryByMyVO> aiHistoryByMyVOS = aiHistoryVOPage.getRecords().stream().map(this::convertToAiHistoryByMyVO).collect(Collectors.toList());

        // 创建新的 Page 对象
        Page<AiHistoryByMyVO> resultPage = new Page<>(aiHistoryVOPage.getCurrent(), aiHistoryVOPage.getSize(), aiHistoryVOPage.getTotal());
        resultPage.setRecords(aiHistoryByMyVOS);

        return ResultUtils.success(resultPage);
    }

    /**
     * 将 AiHistoryVO 转换为 AiHistoryByMyVO
     *
     * @param aiHistoryVO
     * @return
     */
    private AiHistoryByMyVO convertToAiHistoryByMyVO(AiHistoryVO aiHistoryVO) {
        AiHistoryByMyVO aiHistoryByMyVO = new AiHistoryByMyVO();
        aiHistoryByMyVO.setId(aiHistoryVO.getId());
        aiHistoryByMyVO.setUserQuestion(aiHistoryVO.getUserQuestion());
        aiHistoryByMyVO.setAiAnswer(aiHistoryVO.getAiAnswer());
        aiHistoryByMyVO.setCreateTime(aiHistoryVO.getCreateTime());
        return aiHistoryByMyVO;
    }
}
